package client;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.security.cert.X509Certificate;

import common.PasswordStore;
import common.Receiver;
import common.Buffer;
import common.Sender;

public class Client {
	
	private SSLSocket socket;
	private String kspass;
	private String ksfile;
	
	public Client(){
		print("病院のシステムにいらっしゃいませ！");
		String user = prompt("Username:");
		String pw = prompt("User password:");
		ksfile = prompt("Keystore:");
		kspass = prompt("Keystore password:");
		
		setUpSocket();
		Buffer inputBuffer = new Buffer();
		Receiver receiver = new Receiver(socket, inputBuffer);
		receiver.start();
		Sender sender = new Sender(socket);
		sender.start();
		print("Sending authentication");
		sender.send(user); //send username
		String challenge = inputBuffer.poll(); //receive challenge
		String salt = inputBuffer.poll(); //receive salt
		PasswordStore pws = new PasswordStore();
		String response = pws.response(challenge, pw, salt);
		sender.send(response); //send response
		String granted = inputBuffer.poll();
		if (granted.equals("1")){
			print("Access granted by server");
		}else{
			print("Access denied by server");
			System.exit(1);
		}
		print("Opening shell");
		Shell shell = new Shell(sender, inputBuffer, user + "@hospital: $");
		shell.start();
	}

	private void setUpSocket() {
		try {
		    SSLSocketFactory factory = null;
			KeyStore ks = null;
		    try {
				SSLContext ctx;
				KeyManagerFactory kmf;
				char[] passphrase = kspass.toCharArray();
	
				ctx = SSLContext.getInstance("TLS");
				kmf = KeyManagerFactory.getInstance("SunX509");
				ks = KeyStore.getInstance("JKS");
				
				KeyStore localTrustStore = KeyStore.getInstance("JKS");
				localTrustStore.load(new FileInputStream("truststore"), "password".toCharArray());
				
				TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
				tmf.init(localTrustStore);
	
				ks.load(new FileInputStream(ksfile), passphrase);
	
				kmf.init(ks, passphrase);
				ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
	
				factory = ctx.getSocketFactory();
		    } catch (Exception e) {
		    	throw new IOException(e.getMessage());
		    }

		    print("Connecting to server");
		    
		    socket = (SSLSocket)factory.createSocket("localhost", 2000);
		    
		    print("Waiting for certificate");
		    
		    SSLSession session = socket.getSession();
			X509Certificate cert = null;
			try {
				cert = (X509Certificate)session.getPeerCertificateChain()[0];
			} catch (SSLPeerUnverifiedException e) {
				e.printStackTrace();
				return;
			}
			
			print("Connected to server");

		    socket.startHandshake();

		    Thread.sleep(1000);

		} catch (Exception e) {
		    e.printStackTrace();
		}
	}
	
	private void print(String text) {
		System.out.println("EIT060 CLIENT: " + text);
	}
	
	private String prompt(String printstring){
		System.out.print(printstring + " ");
		InputStreamReader converter = new InputStreamReader(System.in);
		BufferedReader in = new BufferedReader(converter);
		try {
			return in.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
